#include "searchAlgo.h"
#include <ctime>
#include <cstdlib>
#include <cassert>

ZobristHashTools::ZobristHashTools()
{
    resetHashTable();
}

ZobristHashTools::~ZobristHashTools()
{

}

void ZobristHashTools::resetHashTable()
{
    for(int x=0; x<DIMENSION; x++)
    {
        for(int y=0; y<DIMENSION; y++)
        {
            for(int z=0; z<4; z++)
            {
                hashTable[x][y][z] = 0;
            }
        }
    }
}

void ZobristHashTools::createHashTable()
{
    srand(time(NULL));

    for(int x=0; x<DIMENSION; x++)
    {
        for(int y=0; y<DIMENSION; y++)
        {
            for(int z=0; z<3; z++)
            {
                hashTable[x][y][z] = rand() * rand();
            }
        }
    }
}

hash_key_t ZobristHashTools::createHashKey(const int board[][DIMENSION])
{
    createHashTable();

    int newHashKey = 0;

    for(int x=0; x<DIMENSION; x++)
    {
        for(int y=0; y<DIMENSION; y++)
        {
            switch(board[x][y])
            {
                case VOID:
                {
                    //newHashKey ^= hashTable[x][y][0];
                    break;
                }
                case BLACK:
                {
                    newHashKey ^= hashTable[x][y][0];
                    break;
                }
                case WHITE:
                {
                    newHashKey ^= hashTable[x][y][1];
                    break;
                }
                case GRID:
                {
                    newHashKey ^= hashTable[x][y][2];
                    break;
                }
                default: assert(0); //the argument passed in is not correct
            }
        }
    }

    return newHashKey;
}

hash_key_t ZobristHashTools::modifyOnePosition(hash_key_t old_hashKey, int pos_x, int pos_y, int color)
{
    int status;

    switch(color)
    {
        //case VOID: new_status = 0; break;
        case BLACK: status = 0; break;
        case WHITE: status = 1; break;
        case GRID: status =2; break;
        default: assert(0);
    }

    //pop this stone from board or add this stone to empty position
    return old_hashKey ^= hashTable[pos_x][pos_y][status];
}
